﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;

namespace ImageComparer
{
    public partial class FormMain : Form
    {
        private Comparer comparer;
        private Boolean waitCursor = true;
        private String selectedList = String.Empty;
        
        public FormMain()
        {
            InitializeComponent();
            this.buttonDelete.Enabled = false;
            this.toolStripStatusLabel3.Text = "Ready";
        }

        private void buttonPath_Click(object sender, EventArgs e)
        {
            try
            {
                FolderBrowserDialog _dialog = new FolderBrowserDialog();
                _dialog.ShowDialog();
                this.textBox1.Text = _dialog.SelectedPath;
            }
            catch (Exception ex) {MessageBox.Show(this, ex.Message + Environment.NewLine + Environment.NewLine + ex.StackTrace, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);}
        }

        private void buttonCompare_Click(object sender, EventArgs e)
        {
            if (this.textBox1.Text != String.Empty)
            {
                this.buttonCompare.Enabled = false;
                this.buttonDelete.Enabled = false;
                this.buttonPath.Enabled = false;
                this.groupBox1.Enabled = false;
                this.checkBox1.Enabled = false;
                this.buttonSusspendResume.Visible = true;
                this.buttonSusspendResume.Text = "Susspend";
                this.checkedListBoxFiles.Items.Clear();
                this.checkedListBoxSimilarFiles.Items.Clear();

                this.toolStripStatusLabel3.Text = "Comparing...";
                this.Cursor = Cursors.WaitCursor;
                this.checkedListBoxFiles.Items.Clear();
                this.checkedListBoxSimilarFiles.Items.Clear();

                comparer = new Comparer(this.textBox1.Text, this.checkBox1.Checked, this.radioButtonPixels.Checked ? true : false);
                comparer.owningWorker = this.backgroundWorker1;

                this.backgroundWorker1.WorkerReportsProgress = true;
                this.backgroundWorker1.WorkerSupportsCancellation = true;
                this.backgroundWorker1.RunWorkerAsync(comparer);
            }
            else
                MessageBox.Show(this, "Please specify folder path.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

        }


        void comparer_errorEvent(object sender, EventArgs e)
        {
            Error(e as ImageComparerEventArgs);
        }

        private void OnSelect1(object sender, EventArgs e)
        {
            this.checkedListBoxSimilarFiles.SelectedIndex = this.checkedListBoxFiles.SelectedIndex;
            LoadImages();
        }
        private void OnSelect2(object sender, EventArgs e)
        {
            this.checkedListBoxFiles.SelectedIndex = this.checkedListBoxSimilarFiles.SelectedIndex;
            LoadImages();
        }
        private void LoadImages()
        {
            this.pictureBox1.LoadAsync(this.checkedListBoxFiles.SelectedItem as String);
            this.pictureBox2.LoadAsync(this.checkedListBoxSimilarFiles.SelectedItem as String);
        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            DialogResult _res = MessageBox.Show(this, "Delete selected images ?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
            if(_res == DialogResult.Yes)
            {
                    this.checkedListBoxFiles.CheckedItems.OfType<String>().ToList().ForEach(_f => File.Delete(_f));
                    this.checkedListBoxSimilarFiles.CheckedItems.OfType<String>().ToList().ForEach(_f => File.Delete(_f));
                    this.checkedListBoxFiles.Items.Clear();
                    this.checkedListBoxSimilarFiles.Items.Clear();
                    this.pictureBox1.Image = null;
                    this.pictureBox2.Image = null;
                    this.toolStripStatusLabel3.Text = "Ready";
                    this.buttonSusspendResume.Visible = false;
            }
        }

        private void Error(ImageComparerEventArgs args)
        {
            this.backgroundWorker1.CancelAsync();
            this.Cursor = Cursors.Default;
            if (this.comparer.imagesPaths1 != null && this.comparer.imagesPaths2 != null && this.comparer.similarImagesPaths != null)
            {
                this.comparer.imagesPaths1.Clear();
                this.comparer.imagesPaths2.Clear();
                this.comparer.similarImagesPaths.Clear();
            }
            this.backgroundWorker1.Dispose();
            this.buttonCompare.Enabled = true;
            this.buttonDelete.Enabled = true;
            this.buttonPath.Enabled = true;
            this.groupBox1.Enabled = true;
            this.checkBox1.Enabled = true;
            this.toolStripStatusLabel3.Text = "Error";

            this.buttonSusspendResume.Visible = true;
            MessageBox.Show(this, args.exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        private void OnHover(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Hand;
            this.waitCursor = false;
        }

        private void OnLeave(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Default;
            this.waitCursor = true;
        }

        private void OnClick(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://pl.pokerstrategy.com/#uPSIWU");
        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            Comparer _comp = (e.Argument as Comparer);
            _comp.StartCompare();
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (this.waitCursor)
                this.Cursor = Cursors.WaitCursor;
            else
                this.Cursor = Cursors.Hand;

            ImageComparerEventArgs _args = e.UserState as ImageComparerEventArgs;
            if(_args != null && _args.eventType == EventType.Compared)
            this.toolStripStatusLabel3.Text = "Compared: "+  _args.comparedCount + " of " + _args.filesCount + " ( " + ((int)(Convert.ToDecimal(_args.comparedCount) / Convert.ToDecimal(_args.filesCount) * 100 )).ToString() + " % ).  Current image progress: " + e.ProgressPercentage.ToString() + " %";

            if (_args != null && _args.eventType == EventType.End) // end of work
            {
                this.toolStripStatusLabel3.Text = _args.filesCount.ToString() + " images compared. Found " + (_args.similarImagesPaths.Count).ToString() +" similar images." ;
                if (_args.similarImagesPaths.Count == 0)
                    this.toolStripStatusLabel3.Text = _args.filesCount.ToString() + " images compared. All images are different.";
                _args.similarImagesPaths.ToList().ForEach(_kv =>
                {
                    this.checkedListBoxFiles.Items.Add(_kv.Key);
                    this.checkedListBoxSimilarFiles.Items.Add(_kv.Value);
                });
            }

            if (_args != null && _args.eventType == EventType.Error)
                Error(_args);

            if (_args != null && _args.eventType == EventType.Susspend)
            {
                this.toolStripStatusLabel3.Text = "Susspended";
                this.Cursor = Cursors.Default;
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Cursor = Cursors.Default;
            if (this.comparer.imagesPaths1 != null && this.comparer.imagesPaths2 != null && this.comparer.similarImagesPaths != null)
            {
                this.comparer.imagesPaths1.Clear();
                this.comparer.imagesPaths2.Clear();
                this.comparer.similarImagesPaths.Clear();
            }
            this.backgroundWorker1.Dispose();
            this.buttonCompare.Enabled = true;
            this.buttonDelete.Enabled = true;
            this.buttonPath.Enabled = true;
            this.groupBox1.Enabled = true;
            this.checkBox1.Enabled = true;

            this.buttonSusspendResume.Visible = false;
        }

        private void buttonSusspendResume_Click(object sender, EventArgs e)
        {
           
            if (this.buttonSusspendResume.Text == "Susspend")
            {
                this.buttonSusspendResume.Text = "Resume";
                this.comparer.Susspend();
            }
            else
            {
                this.buttonSusspendResume.Text = "Susspend";
                this.comparer.Resume();
            }

        }


        private void buttonSusspendResume_MouseLeave(object sender, EventArgs e)
        {
            this.waitCursor = true;
        }

        private void buttonSusspendResume_MouseHover(object sender, EventArgs e)
        {
            this.waitCursor = false;
        }

        private void toolStripMenuItemSelect_Click(object sender, EventArgs e)
        {
            CheckedListBox _list = this.selectedList.Equals(this.checkedListBoxFiles.Name) ? this.checkedListBoxFiles : this.checkedListBoxSimilarFiles;
            int _lenght = _list.Items.Count;

            for (int i = 0; i < _lenght; i++)
                _list.SetItemChecked(i, true);

        }

        private void toolStripMenuItemUnselect_Click(object sender, EventArgs e)
        {
            CheckedListBox _list = this.selectedList.Equals(this.checkedListBoxFiles.Name) ? this.checkedListBoxFiles : this.checkedListBoxSimilarFiles;
            int _lenght = _list.Items.Count;

            for (int i = 0; i < _lenght; i++)
                _list.SetItemChecked(i, false);
        }

        private void contextMenuStrip1_Opened(object sender, EventArgs e)
        {

           this.selectedList =  (sender as ContextMenuStrip).SourceControl.Name;
        }

    }
}
